package com.platform.config;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.platform.interceptor.LogInterceptor;
import com.platform.xss.XssFilter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.config.annotation.*;

import javax.servlet.DispatcherType;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Description: 通用WEB配置，使用时需要被扫描到。
 * 设置了：
 * 日志拦截器，
 * XSS过滤器，
 * 编码过滤器，
 * 基于fastjson的消息转换器，
 * 静态资源映射，
 * 跨域访问
 *
 * @author YangLong [410357434@163.com]
 * @version V1.0
 * @date 2020/8/24
 */
@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Value("${xss.excludedPages}")
    private String excludedPages;

    public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

    @Order(999)
    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter encodingFilter() {
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        return characterEncodingFilter;
    }

    @Bean
    public FilterRegistrationBean<XssFilter> filterRegistrationBean() {
        FilterRegistrationBean<XssFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new XssFilter());
        registrationBean.setInitParameters(Collections.singletonMap("excludedPages", excludedPages));
        registrationBean.setDispatcherTypes(DispatcherType.REQUEST);
        registrationBean.setOrder(999);
        return registrationBean;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LogInterceptor logInterceptor = new LogInterceptor();
        InterceptorRegistration registration = registry.addInterceptor(logInterceptor);
        registration.excludePathPatterns("/statics/**", "/**/**.html", "/**/**.js");
        registration.addPathPatterns("/**");
    }

    /**
     * 设置返回字符串使用UTF-8格式
     *
     * @return message convert
     */
    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        return new StringHttpMessageConverter(StandardCharsets.UTF_8);
    }


    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.SkipTransientField,
                SerializerFeature.QuoteFieldNames,
                SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.DisableCircularReferenceDetect,
                SerializerFeature.WriteBigDecimalAsPlain,
                SerializerFeature.WriteNullListAsEmpty,
                SerializerFeature.WriteNullBooleanAsFalse,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat);
        // WriteDateUseDateFormat 只会格式化Date类型的时候，下面参数可设置LocalDateTime格式的时间
        fastJsonConfig.setDateFormat(DATE_FORMAT);
        //处理中文乱码问题
        List<MediaType> fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.TEXT_HTML);
        fastMediaTypes.add(MediaType.APPLICATION_JSON);
        //支持接口版本控制
        MediaType customMediaType = new MediaType("application", "*+json");
        fastMediaTypes.add(customMediaType);
        fastConverter.setSupportedMediaTypes(fastMediaTypes);
        // 在convert 中添加配置信息
        fastConverter.setFastJsonConfig(fastJsonConfig);
        // 将convert添加到converters当中
        converters.add(responseBodyConverter());
        converters.add(fastConverter);
    }

    /**
     * 配置静态资源
     *
     * @param registry ResourceHandlerRegistry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/",
                        "classpath:/resources/",
                        "classpath:/META-INF/resources/",
                        "classpath:/public/");
        registry.addResourceHandler("/doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");

    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedHeaders("*")
                .allowedMethods("*").maxAge(1800);
        WebMvcConfigurer.super.addCorsMappings(registry);
    }

}
